#!/usr/bin/env python3
import os, time
import argparse, concurrent.futures as cf, sys
import subprocess

from pathlib import Path
from modules.common.config_loader import load_cfg, GlobalCfg
from modules.common.device_utils import list_online_devices, sanitize_sn, filter_available_devices
from modules.common.apk_installer import install_all
from modules.common.activity_loader import load_activity_list  # 你之前添加的
from modules.SRRun.AppStartFactory import AppStartFactory
from modules.common.Logger import Logger
import top300_uninstall

def task_for_device(sn: str, cfg: GlobalCfg):
    # ========== 日志、结果目录 ==========
    res_root = cfg.result_root / sanitize_sn(sn)
    res_root.mkdir(parents=True, exist_ok=True)
    logger = Logger(str(res_root / "runner.log"))

    logger.info("SR Top300: running start")

    # ========== 1. 安装 APK ==========
    #if cfg.auto_install:
    #    install_all(
    #        cfg.apk_dir, device=sn, skip_if_installed=cfg.skip_if_installed
    #    )
    #if cfg.install_only:
    #    logger.info("install_only==true → 结束")
    #    return
    # ========== 2. 执行卸载安装脚本 ==========
    #top300_uninstall.uninstall_apps(sn)
    #top300_uninstall.modify_device_settings(sn)
    # ========== 3. 准备 ActivityInfo ==========
    logger.info(f"task_for_device, activity_list: {cfg.activity_list}")
    package_info_list = load_activity_list(logger, cfg.activity_list)

    # ========== 4. 冷启动测试 ==========
    runner = AppStartFactory(sn, executeView=_build_opts(cfg, package_info_list, sn))
    runner.run()

   
def _build_opts(cfg: GlobalCfg, package_info_list, sn: str):
    """
    返回一个替身对象，字段与旧 UI executeView 对齐，供 AppStartFactory 使用
    """
    class Opt:                    # 轻量壳
        pass

    o = Opt()

    # ───────── 核心必需 ─────────
    o.package_info_list = package_info_list        # {'default':[PackageInfo]}
    o.total_round             = cfg.rounds               # 轮次数
    o.atrace                  = cfg.trace                # 是否抓 trace
    o.async_dump              = False              # 是否 dump meminfo
    o.atrace_duration         = 13                        # 秒
    o.atrace_options          = f"-z -t {o.atrace_duration}"
    o.atrace_options_async    = "-b 10240 rs webview dalvik video binder_driver view hal database wm sm audio power camera memreclaim ss res idle am input sched binder_lock bionic gfx pm"
    o.start_opt               = 0                        # adb am start -W
    o.clean_before            = True                     # 每 APK 启动前清缓存
    o.clean                   = True                     # 每轮结束后再清
    o.app_start_remain        = 13                       # 旧 UI 用来做重跑计数
    o.surfaceFlinger          = False

    # ───────── 日志 / 结果目录 ─────────
    timestamp                = time.strftime("%Y%m%d_%H%M%S")
    o.result_timestamp_dir   = str((cfg.result_root / sn / timestamp).absolute())
    o.result_root = str((cfg.result_root).absolute())
    Path(o.result_timestamp_dir).mkdir(parents=True, exist_ok=True)

    o.log_cycle_type         = "round"      # or 'apk'/'all' 根据需要
    o.memdump_type           = "none"       # 可 'before'/'after'/'round'
    o.dumpsys_type           = "none"       # 其他 dumpsys 采集策略
    o.log_show               = True         # 显示实时日志

    # ───────── 预/后置自定义命令 ─────────
    o.cmd_list_before_apk    = []           # 每 APK 启动前执行
    o.cmd_list_after_apk     = []           # 每 APK 结束后执行
    o.cmd_list_after_round   = []           # 每轮结束后执行

    # ───────── 截图 / 监控 ─────────
    o.screencap              = False
    o.wait_before_screencap  = 0            # 秒

    # ───────── 旧 UI 测试功能占位 ─────────
    o.segCreateTest          = False
    o.round_times_test       = 0
    o.old_test_months        = 0
    o.fragment_percent_test  = 0
    o.size_copy_test         = False
    o.time_to_delay          = 0
    o.clear_for_data         = False

    return o
def resource_path(relative_path):
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath("."), relative_path)
    
    
def main():
    parser = argparse.ArgumentParser(
        description="Multi-device cold-start test runner (no UI)")
    parser.add_argument('-c', '--config', default=resource_path("config.ini"))
    args = parser.parse_args()

    try:
        cfg = load_cfg(args.config)
    except FileNotFoundError as e:
        print(f"错误: {e}")
        sys.exit(1)
    except (KeyError, ValueError) as e:
        print(f"配置错误: {e}")
        sys.exit(1)
    except Exception as e:
        print(f"加载配置失败: {e}")
        sys.exit(1)

    # 获取设备列表
    candidate_sn_list = cfg.device_sn_list or list_online_devices()
    if not candidate_sn_list:
        print("未找到任何设备，退出"); sys.exit(1)

    print(f"候选设备：{', '.join(candidate_sn_list)}")
    
    # 验证设备连接状态
    sn_list = filter_available_devices(candidate_sn_list)
    if not sn_list:
        print("没有可用的设备，退出"); sys.exit(1)

    print(f"可用设备：{', '.join(sn_list)}")
    with cf.ThreadPoolExecutor(max_workers=len(sn_list)) as ex:
        futs = [ex.submit(task_for_device, sn, cfg) for sn in sn_list]
        for f in cf.as_completed(futs):
            f.result()  # 让异常直接抛出

if __name__ == '__main__':
    main()
